
/*
SSD1289 3.2" TFT LCD Functions for PIC32MX795F512L PMP
Copyright (C) 2012 Craig Dawson, Aaron Mohtar, Craig Peacock

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

#include "SSD1289.h"

void pmpInit(void)
{
    PMCONbits.PTWREN = 1;   // Enable write strobe (PMWR)
    PMCONbits.PTRDEN = 1;   // Enable read strobe (PMRD)
    PMCONbits.CSF = 0b10;   // PMCS2 and PMCS1 function as chip select

    PMMODEbits.MODE16 = 1;  // Enable 16 bit mode
    PMMODEbits.MODE = 0b10; // Master mode 2 (Seperate RD and RW strobes)

    PMADDRbits.CS1 = 1;     // Chip select 1 is active

    PMAENbits.PTEN0 = 1;    // PMALL functions as A0
    PMAENbits.PTEN14 = 1;   // PMA14 functions as CS

    // 1 wait state is equal to one peripheral bus clock cycle (TPBCLK) 12.5nS
    PMMODEbits.WAITB = 0b00;    // 1TPB Data setup prior to RD/WR strobe
    PMMODEbits.WAITM = 0b0001;  // Width of RD/WR strobe (2TPB = 25nS)
    PMMODEbits.WAITE = 0b00;    // Data hold time after RD/WR strobe
                                // Write 1TPB, Read 0TPB

    PMCONbits.ON = 1;       // Enable Parallel Master Port
}

void lcdBlInit(unsigned int brightness)
{
    // The HY32D 3.2" TFT LCD Display Module is fitted with an
    // OnSemi CAT6219 LDO regulator to power the LCD backlight.
    // The enable pin of the regulator is connected to OC2.
    // Timer 2 (16 bit mode) is the source for Output Compare 2

    // If brightness = 0%,   LCD backlight is off.
    // If brightness = 100%, LCD backlight is on.

    // 80MHz TPBCLK / Prescaler 64 / 100 counts of PR2 = 12.5KHz
    T2CONbits.TCKPS = 0b110;    // 1:64 Prescaler
    PR2 = 99;                   // Set the PWM Period
    T2CONbits.ON = 1;           // Turn on timer 2
    
    OC2CONbits.OCM = 0b110;     // PWM mode, fault pin disabled.
    OC2RS = brightness;         // Set the PWM duty cycle
    OC2CONbits.ON = 1;          // Finally, turn on OC2
}

void lcdBlSetBrightness(unsigned int brightness)
{
    OC2RS = brightness;         // Set the PWM duty cycle
}

void lcdInit(void)
{
    RES_DIR = 0;    // Make the reset pin an output;

    RES = 1;
    delayMs(5);

    RES = 0;
    delayMs(10);

    RES = 1;
    delayMs(200);

    lcdSendCommand(0x00, 0x0001); // Start Internal OSC
    delayMs(15);

    lcdSendCommand(0x03, 0xA2A4); 
    lcdSendCommand(0x0c, 0x0002);
    lcdSendCommand(0x0d, 0x000a);
    lcdSendCommand(0x0e, 0x2c00);
    lcdSendCommand(0x1e, 0x00b8);
    delayMs(15);

    lcdSendCommand(0x01, 0x2B3F); // Driver Output Control, REV=0, BGR=0, GD=0, SM=0, TB=0, RL=1
    lcdSendCommand(0x02, 0x0600); // LCD Driving Wafworm Control, B/C=0, EOR=0
    lcdSendCommand(0x10, 0x0000); // Exit sleep mod
    lcdSendCommand(0x11, 0x6030); // Entry Mode, ID[1:0]=11, AM=0
    delayMs(20);

    lcdSendCommand(0x05, 0x0000);
    lcdSendCommand(0x06, 0x0000);

    lcdSendCommand(0x16, 0xef1c);
    lcdSendCommand(0x17, 0x0003);

    lcdSendCommand(0x07, 0x0033);

    lcdSendCommand(0x0b, 0x5312);
    lcdSendCommand(0x0f, 0x0000);
    delayMs(20);

    lcdSendCommand(0x41, 0x0000); // Vertical Scroll Control
    lcdSendCommand(0x42, 0x0000);

    lcdSendCommand(0x44, 0xef00); // Horizontal RAM address posistion
    lcdSendCommand(0x45, 0x0000); // Vertial RAM address position
    lcdSendCommand(0x46, 0x013f);

    lcdSendCommand(0x48, 0x0000); // 1st Screen driving position
    lcdSendCommand(0x49, 0x013f);

    lcdSendCommand(0x4a, 0x0000); // 2nd Screen driving position
    lcdSendCommand(0x4b, 0x013f);
    delayMs(30);

    //gamma control
    lcdSendCommand(0x0030, 0x0707);
    lcdSendCommand(0x0031, 0x0704);
    lcdSendCommand(0x0032, 0x0204);
    lcdSendCommand(0x0033, 0x0201);
    lcdSendCommand(0x0034, 0x0203);
    lcdSendCommand(0x0035, 0x0204);
    lcdSendCommand(0x0036, 0x0204);
    lcdSendCommand(0x0037, 0x0502);
    lcdSendCommand(0x003A, 0x0302);
    lcdSendCommand(0x003B, 0x0500);

    lcdSendCommand(0x4e, 0x0000); // RAM address set
    lcdSendCommand(0x4f, 0x0000);

    lcdWriteCom(0x22);
}


void lcdSetAddress(unsigned int x1,unsigned int y1,unsigned int x2,unsigned int y2)
{
    lcdSendCommand(0x0044, (x2 << 8) + x1); // Horizontal RAM address position

    lcdSendCommand(0x0045, y1); // Vertical RAM address start position
    lcdSendCommand(0x0046, y2); // Vertical RAM address end position

    lcdSendCommand(0x4E, x1);   // Set GDDRAM X address counter
    lcdSendCommand(0x4F, y1);   // Set GDDRAM Y address counter

    lcdWriteCom(0x0022);        // Set register to RAM Data ready
                                // for writing to GDDRAM
}

//-------------------------------
// Usage: lcdSetPixel(5,10,BLACK)
// Sets pixel at (x,y) to the colour specified
//-------------------------------
void lcdSetPixel(unsigned int x, unsigned int y, unsigned int colour)
{
    lcdSetAddress(x, y, x, y);
    lcdWriteData(colour);
}
